/*
 Copyright 2014-Present Algorithms in Motion LLC
 
 This file is part of FDTD++.
 
 FDTD++ is proprietary software: you can use it and/or modify it
 under the terms of the Algorithms in Motion License as published by
 Algorithms in Motion LLC, either version 1 of the License, or (at your
 option) any later version.
 
 FDTD++ is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 Algorithms in Motion License for more details.
 
 You should have received a copy of the Algorithms in Motion License
 along with FDTD++. If not, see <http://www.aimotionllc.com/licenses/>.
*/
// CREATED    : 3/16/2015
// LAST UPDATE: 3/16/2015

#include "resampling.hpp"

// STL
#include <algorithm>       // std::min()
#include <utility>         // std::pair<>, std::make_pair()
#include <vector>          // std::vector<>


//========================================================================
//========================================================================
//
// NAME: std::pair<std::vector<unsigned int>, std::vector<unsigned int>> statsxx::resampling::kfold_indices( const unsigned int n1, const unsigned int n2, const unsigned int nk )
//
// DESC: For k-fold cross validation, find the indices of all k folds.
//
// INPUT:
//     unsigned int n1 : Start index (of all k folds)
//     unsigned int n2 : End index
//     unsigned int nk : Number of folds
//     unsigned int k  : The kth fold (0, 1, ..., nk-1)
//
// INPUT:
//     unsigned int k1 : Start index (of the kth fold)
//     unsigned int k2 : End index
//
// << jmm: this routine is nearly identical to the other kfold_indices(). the reason it is written out here (again) is that it *appears* to avoid multiple computations of work1 and work2. however, I am curious if we did just call the other kfold_indices(), if most modern compilers would be smart enough to actually remove work1 and work2 from the loop anyway? >>
//
//========================================================================
//========================================================================
std::pair<std::vector<unsigned int>, std::vector<unsigned int>> statsxx::resampling::kfold_indices( const unsigned int n1, const unsigned int n2, const unsigned int nk )
{
    std::vector<unsigned int> k1(nk), k2(nk);

    unsigned int work1 = (n2 - n1 + 1) / nk;
    unsigned int work2 = (n2 - n1 + 1) % nk;
    
    for( unsigned int k = 0; k < nk; ++k )
    {
        k1[k] = k*work1 + n1 + std::min(k, work2);
        k2[k] = k1[k] + work1 - 1;
        
        if( work2 > k )
        {
            ++k2[k];
        }
    }

    return std::make_pair(k1, k2);
}


//========================================================================
//========================================================================
//
// NAME: std::pair<unsigned int, unsigned int> statsxx::resampling::kfold_indices( const unsigned int n1, const unsigned int n2, const unsigned int nk, const unsigned int k )
//
// DESC: For k-fold cross validation, find the indices of the kth fold.
//
// INPUT:
//     unsigned int n1 : Start index (of all k folds)
//     unsigned int n2 : End index
//     unsigned int nk : Number of folds
//     unsigned int k  : The kth fold (0, 1, ..., nk-1)
//
// INPUT:
//     unsigned int k1 : Start index (of the kth fold)
//     unsigned int k2 : End index
//
//========================================================================
//========================================================================
std::pair<unsigned int, unsigned int> statsxx::resampling::kfold_indices( const unsigned int n1, const unsigned int n2, const unsigned int nk, const unsigned int k )
{
    unsigned int work1 = (n2 - n1 + 1) / nk;
    unsigned int work2 = (n2 - n1 + 1) % nk;
        
    unsigned int start = k*work1 + n1 + std::min(k, work2);
    unsigned int end   = start + work1 - 1;

    if( work2 > k )
    {
        ++end;
    }
    
    return std::make_pair(start, end);
}
